<template>
  <div class="container">
    <div class="app-container">
      <div class="left" v-loading="leftLoading">
        <el-input
        @input="changeValue"
        v-model="queryParams.keyword" 
        style="margin-bottom:10px" type="text" prefix-icon="el-icon-search" size="small" placeholder="输入员工姓名" />
        <!-- 树形组件 -->
        <el-tree
        ref="deptTree"
        node-key="id"
        v-if="depts.length > 0" 
        :data="depts" 
        :props="defaultProps" 
        default-expand-all
        :expand-on-click-node="false"
        :highlight-current="true"
        @node-click="selectNode"
        >

        </el-tree>
      </div>
      <div class="right" v-loading="rightLoading">
        <el-row class="opeate-tools" type="flex" justify="end">
          <el-button
          v-permission="'add-employee'"
           @click="$router.push('/employee/detail')"
          size="mini" 
          type="primary">添加员工</el-button>
          <el-button 
          v-permission="'import-employee'"
          @click="showExcelDialog=true"  size="mini">excel导入</el-button>
          <el-button
          v-permission="'export-employee'" @click="exportEmployees"  size="mini">excel导出</el-button>
        </el-row>
        <!-- 表格组件 -->
        <template v-if="employeeList.length>0">
          <!-- 放置表格 -->
        <el-table 
        stripe
        :data="employeeList"
        >
          <el-table-column
          align="center"
          label="头像" 
          prop="staffPhoto" 
          >
          <template #default="{row}">
            <!-- 头像组件 -->
            <el-avatar v-if="row.staffPhoto"
            :src="row.staffPhoto"
            :size="30"
            >

            </el-avatar>
            <span v-else class="username">{{row.username.charAt(0)}}</span>


          </template>
          </el-table-column>
          <el-table-column 
          label="姓名" 
          prop="username"
          align="center"

          >

          </el-table-column>
          <el-table-column 
          label="手机号"
          sortable
          prop="mobile"
          width="110px"
          align="center"
          >

          </el-table-column>
          <el-table-column 
          label="工号" 
          sortable
          prop="workNumber"
          align="center"
          width="110px"

          >

          </el-table-column>
          <el-table-column 
          label="聘用形式"
          prop="formOfEmployment"
          align="center"
          width="110px"
          
          >

          <template #default="{row}">
            <span v-if="row.formOfEmployment===1">正式</span>
            <span v-else-if="row.formOfEmployment===2">非正式</span>
            <span v-else>无</span>
          </template>
          </el-table-column>
          <el-table-column 
          label="部门" 
          prop="departmentName"
          align="center"
          width="110px"
          >

          </el-table-column>
          <el-table-column 
          label="入职时间"
          prop="timeOfEntry"
          align="center"
          width="110px"
          >

          </el-table-column>
          <el-table-column 
          label="操作"
          width="280px"
          prop="staffPhoto"
          align="center"

          >
            <template #default="{row}">
              <el-button
               @click="$router.push(`employee/detail/${row.id}`)"
               type="text"
               >查看</el-button>
              <el-button
              @click="btnRole(row.id)"
               type="text"
               >角色</el-button>
               <!-- 气泡确认框 -->
               <el-popconfirm
               confirm-button-text='确定'
               cancel-button-text='取消'
               icon="el-icon-info"
               icon-color="red"
               title="确定删除吗？"
               @onConfirm="confirmDel(row.id)"
               >
               <el-button
               slot="reference"
               type="text"
               style="margin-left:10px;"
               
               >删除</el-button>
               </el-popconfirm>
               

            </template>
          </el-table-column>

          
        </el-table>
          
        </template>
        
        <!-- 无数据显示空状态(vue2中没有空状态组件) -->
        <div v-else class="empty-state">
        <i class="el-icon-document"></i>
        <p>暂无数据</p>
        </div>
        <!-- 分页 -->
        <el-row type="flex" justify="center" 
        align="middle" 
        style="height:60px;"
        >
        <el-pagination
         background
        layout="total,prev, pager, next"
        :total="total"
        :page-size="queryParams.pagesize"
        :current-page="queryParams.page"
        @current-change="changePage"
        >

        </el-pagination>
          
        </el-row>
      </div>
    </div>
    <!-- 放置文件导入弹层组件 -->
    <ImportExcel
    :showExcelDialog.sync="showExcelDialog"
    @updateSuccess="getEmployeeLists"
    ></ImportExcel>
    <!-- 放置分配角色弹层 -->
    <el-dialog
    title="分配角色" 
    :visible.sync="showDialog"
    :append-to-body="true"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    width="600px" 
    center
    >
    <!-- checkbox（多选框）组 -->
    <el-checkbox-group
    v-model="roleIds"
    >
    <!-- 放置checkbox（多选框） -->
    <!-- 注意：这里要给checkbox添加label属性，用来存储选中的值，这里我们存储id（以接口文档为主） -->
    <el-checkbox v-for="item in roleList" :key="item.id" :label="item.id">{{item.name}}</el-checkbox>
    </el-checkbox-group>
    <!-- 确定取消按钮  -->
    <!-- 将按钮通过el-dialog组件自带的footer具名插槽进行插入，避免了不必要的样式 -->
    <el-row slot="footer" type="flex" justify="center">
      <el-col :span="24">
        <el-button type="primary"
        @click="btnOk"
        style="margin-right:20px;"
        >确定</el-button>

        <el-button 
        @click="showDialog=false"
        >取消</el-button>
      </el-col>
    </el-row>
     
    </el-dialog>
  </div>
</template>

<script>

import FileSaver from 'file-saver'//引入文件下载到本地的包
import {getDepartment} from '@/api/department'
import {transListToTreeData,processDepartmentData} from '@/utils'
import {getEmployeeList,exportEmployee,delEmployee,getEnableRoleList,getEmployeeDetail,assignRole} from '@/api/employee'
import ImportExcel from './components/import-excel.vue'
import {Message} from 'element-ui'
export default {
  name: 'Employee',
  components:{
    ImportExcel
  },
  created(){
    this.getDepartments()
  },
  data(){
    return {
      Timer:null,//储存防抖所用的定时器
      leftLoading:false,//控制组织架构数据懒加载状态
      rightLoading:false,//控制员工列表表格数据懒加载状态
      depts:[],//组织架构数据初始化
      defaultProps:{
        // 注意：tree组件中只有label和children这两个属性是必须的,它是tree组件内部规定的，如果在数据中还有其他字段名，就表明该数据是自定义的不必写入其中,比如上面的managerName
        label:'name',//要显示的字段的名字(以接口为主)
        children:'children',//读取子节点字段名
      },
      // 查询参数初始化
      queryParams:{
        departmentId:null,//部门id,部门id,根据部门查询当前部门及子部门的用户
        page:1,//当前页
        pagesize:10,//当前页总条数(每页总条数)
        keyword:''//根据名字模糊查询

      },
      // 记录员工总数
      total:0,
      // 员工列表数据初始化
      employeeList:[],
      // 控制excel弹层显示和隐藏
      showExcelDialog:false,
      // 控制分配角色弹层显示和隐藏
      showDialog:false,
      // 可分配的角色列表数据初始化
      roleList:[],
      // 存储选中的角色id数据初始化
      roleIds:[],
      // 记录存储当前点击用户的id
      currentUserId:null
    }

  },
  methods:{
    // 获取组织架构数据
    async getDepartments(){
      this.leftLoading=true//获取数据前开启加载
      const res=await getDepartment()
      /*由于前端渲染需要修改后端传过来的数据，所以需要对数据进行处理*/
      
      //对返回的数据进行切片处理，并赋值
      const resList=processDepartmentData(res)
      
      // 将resList转换为树形结构数据,并赋值给数据属性depts，方便前端渲染
      this.depts=transListToTreeData(resList,0)
      // console.log(this.depts);
      // 记录数据中首节点的id，并储存起来
      this.queryParams.departmentId=this.depts[0].id
      //通过调用树组件中的方法并根据记录的id设置首节点选中实现默认高亮
      // 注意：由于树组件渲染是异步的，所以必须等数据渲染完成才能执行后续代码
      this.$nextTick(()=>{
         // 此时树组件已经渲染完毕
         // 将同步方法包裹在其中，方便与异步方法执行正确的逻辑
         this.$refs.deptTree.setCurrentKey(this.queryParams.departmentId)
      })
      // 这个时候id已经记录，也就是说默认选中并高亮的那个节点需要默认渲染
      this.getEmployeeLists()
      this.leftLoading=false//获取数据后关闭加载
      
    },
    // 点击选中节点时触发
    selectNode(node){
      console.log(node);
      this.queryParams.departmentId=node.id
      // 点击不同id（部门）时渲染该部门下的数据，但是必须是从第一页开始渲染
      this.queryParams.page=1
      // 切换节点后渲染对应数据
      this.getEmployeeLists()

    },
    // 获取员工列表数据
    async getEmployeeLists(){
     this.rightLoading=true//获取数据前开启加载
     const {rows,total}=await getEmployeeList(this.queryParams)
    //  console.log(rows,total);
     //对返回的数据进行切片处理，并赋值
     this.employeeList=processDepartmentData(rows)
     this.total=total
    //  console.log(this.employeeList);
     this.rightLoading=false//获取数据后关闭加载
    },
    // 切换页码时触发
    changePage(newPage){
      // console.log(newPage);
      // 切换页码时得到新页码，并赋值给queryParams.page
      this.queryParams.page=newPage
      // 重新查询，渲染最新页码的数据
      this.getEmployeeLists()

    },
    // 输入框内容改变时触发
    changeValue(value){
      // 因为已经实现双向绑定这里的value等同于this.queryParams.keyword，可以不用传参
      // console.log(value);
      // console.log(this.queryParams.keyword);

      /*防抖处理,避免重复多次请求 */

      // 清除上一次的定时器
      if (this.Timer) {
        clearTimeout(this.Timer)
      }
      // 重新设置定时器
      this.Timer = setTimeout(() => {
         // 模糊字段输入完毕后，在获取相应最新的数据前，应当让数据在第一页显示，然后渲染最新数据
         this.queryParams.page=1
         this.getEmployeeLists()
      }, 500)
     
    },
    // 导出员工的excel
    async exportEmployees(){
      // 调用员工的excel接口数据
      const result=await exportEmployee()
      console.log(result);
      // 此时result是一个二进制流文件，我们需要使用一个npm包，导入并使用，直接将blob文件下载到本地
      // 命令： pnpm i file-saver
      // FileSaver.saveAs(blob对象，文件名称)
      FileSaver.saveAs(result,'员工信息表.xlsx')
    },
    // 在确认框中点击确定时调用删除员工接口
    async confirmDel(id){
      // console.log(id);
      await delEmployee(id)
      // 提示用户
      Message.success('删除成功')
      // 注意：删除后，如果删除的是最后一个数据，此时后端没有数据，渲染前，前端还有一条数据，等后续进行回显渲染时，应该当前页码减一，渲染前一页数据，并且如果是最后一条数据但是在第一页，那么不进行页码减一，应该直接渲染，毕竟页码不能为负数
      if(this.employeeList.length===1&&this.queryParams.page>1){
        this.queryParams.page--
      } 
      // 重新加载渲染数据
      this.getEmployeeLists()
      
    },
    // 点击角色按钮弹出层
    async btnRole(id){
      // 获取角色数据
      const result=await getEnableRoleList()
      // console.log(result,id);
      this.roleList=result
      // 记录保存当前点击的id，用于后边提交数据
      this.currentUserId=id
      // 通过对应id获取当前点击用户的详情数据，解构出里面的roleIds数据，赋值给roleIds，实现与多选框组的双向绑定，这样点击角色时弹层中就会有默认的角色勾选上了
      // 拿到角色详情数据中的roleIds
      const {roleIds}=await getEmployeeDetail(id)
      // console.log(roleIds);
      this.roleIds=roleIds
      // 在该功能中等所有数据获取完毕在显示弹层，这样比较流畅，用户体验好
      this.showDialog=true
    },
    // 点击弹层中确定时触发
    async btnOk(){
      // 提交分配好的角色数据
      await assignRole({
        id:this.currentUserId,
        roleIds:this.roleIds
      })
      // 成功后，提示用户
      Message.success('分配角色成功')
      // 关闭弹层
      this.showDialog=false
    }

  }
}
</script>

<style lang="scss" scoped>
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%; /* 固定高度，或使用 100% */
  color: #999;
  font-size: 16px;
  text-align: center;
}
.empty-state i {
  font-size: 60px;
  margin-bottom: 10px;
  color: #ccc;
}
.empty-state p {
  margin: 0;
  font-size: 16px;
}
.app-container {
  background: #fff;
  display: flex;
  .left {
    width: 280px;
    padding: 20px;
    border-right: 1px solid #eaeef4;
  }
  .right {
    flex: 1;
    padding: 20px;
    .opeate-tools {
      margin:10px ;
    }
    .username {
      height: 30px;
      width: 30px;
      line-height: 30px;
      text-align: center;
      border-radius: 50%;
      color: #fff;
      background: #04C9BE;
      font-size: 12px;
      display:inline-block;
    }
  }
}

</style>